<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死，可以将下面declare打开（去掉//注释），并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */
//declare(ticks=1);

/**
 * 聊天主逻辑
 * 主要是处理 onMessage onClose 
 */
use \GatewayWorker\Lib\Gateway;
use \GatewayWorker\Lib\Db;
use \GatewayWorker\Lib\DbConnection;
use \Workerman\Lib\Timer;
require 'lib\utility.php';
require 'lib\user.lib.php';
require 'lib\Game.lib.php';
require 'lib\Chat.lib.php';
class Events
{
	public static $db = null;
   /**
    * 有消息时
    * @param int $client_id
    * @param mixed $message
    */
	
	/**
     * 进程启动后初始化数据库连接
     */
    public static function onWorkerStart($worker)
    {
        self::$db = Db::instance('db');
    }
	public static function onConnect($client_id)
    {
		
    }
   public static function onMessage($client_id, $message)
   {
	   // debug
        echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']}  client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n";
        // 客户端传递的是json数据
        $paras = json_decode($message, true);
        if(!$paras)
        {
            echo 'para error!';
			return ;
        }
        //默认返回数据
		$result = array('type'=>$paras['type'], 'state'=>404, 'msgid'=>10006, 'client_id'=>$client_id, 'time'=>time());// 'time'=>date('Y-m-d H:i:s'));
		
        // 根据类型执行不同的业务
        switch($paras['type'])
        {
			//聊天室列表
			case 'chatroomslist':
                //从库中取出房间数据
				$roomslist = self::$db->select('`name`,`explain`,`icon`,`roomtype`')->from('rp_rooms')->where('state=1')->query();//self::$db->query($sql);
				$result['rooms'] = $roomslist;
				//在线人数
				$result['onlinenums'] = Gateway::getAllClientCount();
                return Gateway::sendToCurrentClient(json_encode($result));
				break;
            // 客户端回应服务端的心跳
            case 'pong':
                return;
			// 庄家结束下注并开始发红包，把下注开关置为0，系统重新计算下注人数、金额、并计算是否有足够的金币来结算
			// 庄家金币不足时提示赚金币且须在3分钟内完成，否则本次下注无效或通赔，扣除庄家上庄的全部金币并取消庄家资格
			case 'endbetingandsendpaper':
				return;
			//拉取用户信息
			case 'getuserinfo':
				$uid = utility::existsKeyInArray('uid',$paras,'N');
				$username = utility::existsKeyInArray('username',$paras,'S');
				echo 'userid='.$uid;
				$testToken = self::exitsToKen($paras,$result);
				if($testToken['state']==200){
					if($uid){
						$user = self::$db->row("SELECT `id`,`coin`,`nickname`,`username`,`usertype` FROM `rp_users` WHERE `id`={$uid} LIMIT 1");
						if($user){
							$result['state'] = 200;
							$result['coin'] = number_format($user['coin'],2);
							$result['username'] = $user['username'];
							$result['nickname'] = $user['nickname'];
							$result['uid'] = $user['id'];
							$result['usertype'] = $user['usertype'];
						}
					}
				}else{
					$result['state'] = $testToken['state'];
					$result['msgid'] = $testToken['msgid'];
				}
				Gateway::sendToCurrentClient(json_encode($result));
				return;
			//发送红包（实际为转帐功能）
			case 'sendtousercoin':
				$username = utility::existsKeyInArray('username',$paras,'S');
				$sendcoin = utility::existsKeyInArray('sendcoin',$paras,'F');
				$sendtouid = utility::existsKeyInArray('sendtouid',$paras,'N');
				$testToken = self::exitsToKen($paras,$result);
				if($testToken['state']==200){
					//查找当前用户的可用金币
					$user = self::$db->row("SELECT `coin` FROM `rp_users` WHERE `username`='{$username}'");
					if(floatval($user['coin']) >= $sendcoin){
						//扣除当前玩家的余额
						$_count = self::$db->query("UPDATE `rp_users` SET `coin` = `coin`-".$sendcoin." WHERE `username`='".$username."'");
						if($_count){
							//存入目标玩家
							$m_count = self::$db->query("UPDATE `rp_users` SET `coin` = `coin`+".$sendcoin." WHERE `id`='".$sendtouid."'");
							if($m_count){
								$result['state'] = 200;
								$result['msgid'] = 10007;
								//通知玩家收取红包
								Gateway::sendtouid($sendtouid,json_encode($result));
							}else{
								$result['msgid'] = 10008;
							}
						}else{
							$result['msgid'] = 10006;
						}
						
						
					}else{
						$result['msgid'] = 10005;
					}
				}else{
					$result['state'] = $testToken['state'];
					$result['msgid'] = $testToken['msgid'];
				}
				Gateway::sendToCurrentClient(json_encode($result));
				return;
			// 拉取房间规则
			case 'roomrule':
			//用户金币余额
			case 'getuserfreecoin':
				$username = utility::existsKeyInArray('username',$paras,'S');
				$testToken = self::exitsToKen($paras,$result);
				if($testToken['state']==200){
					$coin = 0.00;
					$user = self::$db->row("SELECT `coin` FROM `rp_users` WHERE `username`='{$username}'");
					if($user){
						$result['state'] = 200;
						$result['msg'] = '';
						$result['coin'] = number_format($user['coin'],2);
					}else{
						$result['msgid'] = 10000;
					}
				}else{
					$result['state'] = $testToken['state'];
					$result['msgid'] = $testToken['msgid'];
				}
				Gateway::sendToCurrentClient(json_encode($result));
				return;
			//用户帐号注册
			case 'register':
				$username = utility::existsKeyInArray('username',$paras,'S');
				$password = utility::existsKeyInArray('password',$paras,'S');
				$nickname = utility::existsKeyInArray('nickname',$paras,'S');
				$repassword = utility::existsKeyInArray('repassword',$paras,'S');
				$usertype = utility::existsKeyInArray('usertype',$paras,'N');
				if(empty($username)){
					$result['msg'] = '用户名不能为空';
					return Gateway::sendToCurrentClient(json_encode($result));
				}
				if(empty($password)){
					$result['msg'] = '登录密码不能为空';
					return Gateway::sendToCurrentClient(json_encode($result));
				}
				if($password != $repassword){
					$result['msg'] = '两次密码输入不一致';
					return Gateway::sendToCurrentClient(json_encode($result));
				}
				//检测用户名是否已被注册
				$user = self::$db->row("SELECT `id` AS _TOTAL FROM `rp_users` WHERE `username`='{$username}'");
				if($user){
					$result['msg'] = '登录帐号已存在，请重试';
					return Gateway::sendToCurrentClient(json_encode($result));
				}
				//生成密码token
				$token = utility::randString(4);
				$makePasswd = utility::encrypt($password,'E',$token);
				$webtoken = utility::settoken($username);
				
				$insert_data = array(
					'username'=>$username,
					'passwd'=>$makePasswd,
					'regtimes'=>time(),
					'regip'=>bindec(decbin(ip2long($_SERVER['REMOTE_ADDR']))),
					'usertype'=>$usertype,
					'lastlogintimes'=>time(),
					'token'=>$token,
					'webtoken'=>$webtoken,
				);
				$insert_id = self::$db->insert('rp_users')->cols($insert_data)->query();
				
				Gateway::bindUid($client_id, $insert_id);
				
				$result['state'] = 200;
				$result['userid'] = $insert_id;
				$result['username'] = $username;
				$result['usertype'] = $usertype;
				$result['token'] = $webtoken;
				$result['msg'] = 'success';
				$result['client_id'] = $client_id;
				return Gateway::sendToCurrentClient(json_encode($result));
			// 用户帐号登录
			case 'userlogin':
				//查询用户是否存在
				$username = utility::existsKeyInArray('un',$paras,'S');
				$password = utility::existsKeyInArray('pw',$paras,'S');

				$user = self::$db->row("SELECT `id`,`username`,`passwd`,`lastlogintimes`,`usertype`,`token`,`webtoken` FROM `rp_users` WHERE `username`='{$username}'"); //self::$db->query($sql);
				$makePasswd = utility::encrypt($password,'E',$user['token']);
				if(!$user){
					$result['msgid'] = 10003;
					return Gateway::sendToCurrentClient(json_encode($result));
				}else{
					if($user['passwd'] != $makePasswd){
						$result['msgid'] = 10004;
						return Gateway::sendToCurrentClient(json_encode($result));
					}else{
						$result['state'] = 200;
						$token = $user['webtoken'];
						unset($user['passwd']);
						unset($user['token']);
						unset($user['webtoken']);
						$result['user'] = $user;
						Gateway::bindUid($client_id, $user['id']);
					}
				}
				//生成密码token
				$webtoken = utility::settoken($user['username']);
				//保存token
				$row_count = self::$db->update('rp_users')->cols(array('webtoken'=>$webtoken,'lastlogintimes'=>time()))->where('`id`='.$user['id'])->query();
				$result['token'] = $webtoken;
				return Gateway::sendToCurrentClient(json_encode($result));
			//检测用户登录验证token时效性
			case 'checklogin':
				$username = utility::existsKeyInArray('username',$paras,'S');
				$token = utility::existsKeyInArray('token',$paras,'S');
				return;
            // 客户端登录到房间 message格式: {type:login, name:xx, room_id:1} ，添加到客户端，广播给所有客户端xx进入聊天室
            case 'loginchatroom':
                // 判断是否有房间号
                if(!isset($paras['room_id']))
                {
                    throw new \Exception("\$paras['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message");
                }
                // 把房间号昵称放到session中
                $room_id = $paras['room_id'];
                $client_name = htmlspecialchars($paras['client_name']);
                $_SESSION['room_id'] = $room_id;
                $_SESSION['client_name'] = $client_name;
              
                // 获取房间内所有用户列表 
                $clients_list = Gateway::getClientSessionsByGroup($room_id);
                foreach($clients_list as $tmp_client_id=>$item)
                {
                    $clients_list[$tmp_client_id] = $item['client_name'];
                }
                $clients_list[$client_id] = $client_name;
                
                // 转播给当前房间的所有客户端，xx进入聊天室 message {type:login, client_id:xx, name:xx} 
                $new_message = array(
					'type'=>$paras['type'], 
					'client_id'=>$client_id, 
					'client_name'=>htmlspecialchars($client_name),
					'client_usertype'=>1,
					'state'=>200,
					'time'=>date('Y-m-d H:i:s')
				);
                Gateway::sendToGroup($room_id, json_encode($new_message));
                Gateway::joinGroup($client_id, $room_id);
               
                // 给当前用户发送用户列表 
                $new_message['client_list'] = $clients_list;
                Gateway::sendToCurrentClient(json_encode($new_message));
                return;
                
            // 客户端发言 message: {type:say, to_client_id:xx, content:xx}
            case 'say':
                // 非法请求
                if(!isset($_SESSION['room_id']))
                {
                    throw new \Exception("\$_SESSION['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']}");
                }
                $room_id = $_SESSION['room_id'];
                $client_name = $_SESSION['client_name'];
                
                // 私聊
                if($paras['to_client_id'] != 'all')
                {
                    $new_message = array(
                        'type'=>'say',
						'client_id'=>$client_id,
                        'from_client_id'=>$client_id, 
                        'from_client_name' =>$client_name,
                        'to_client_id'=>$paras['to_client_id'],
                        'content'=>"<b>对你说: </b>".nl2br(htmlspecialchars($paras['content'])),
                        'time'=>date('Y-m-d H:i:s'),
                    );
                    Gateway::sendToClient($paras['to_client_id'], json_encode($new_message));
                    $new_message['content'] = "<b>你对".htmlspecialchars($paras['to_client_name'])."说: </b>".nl2br(htmlspecialchars($paras['content']));
                    return Gateway::sendToCurrentClient(json_encode($new_message));
                }
                
                $new_message = array(
                    'type'=>'say',
					'client_id'=>$client_id,
                    'from_client_id'=>$client_id,
                    'from_client_name' =>$client_name,
                    'to_client_id'=>'all',
                    'content'=>nl2br(htmlspecialchars($paras['content'])),
                    'time'=>date('Y-m-d H:i:s'),
                );
                return Gateway::sendToGroup($room_id ,json_encode($new_message));
        }
   }
   
   /**
    * 当客户端断开连接时
    * @param integer $client_id 客户端id
    */
   public static function onClose($client_id)
   {
       // debug
       echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']}  client_id:$client_id onClose:''\n";
       
       // 从房间的客户端列表中删除
       if(isset($_SESSION['room_id']))
       {
           $room_id = $_SESSION['room_id'];
           $new_message = array('type'=>'logout', 'from_client_id'=>$client_id, 'from_client_name'=>$_SESSION['client_name'], 'time'=>date('Y-m-d H:i:s'));
           Gateway::sendToGroup($room_id, json_encode($new_message));
       }
   }
   //验证帐号及token有效性
   public static function exitsToKen($paras,$result){
		$username = utility::existsKeyInArray('username',$paras,'S');
		$token =  utility::existsKeyInArray('token',$paras,'S');
		$user = self::$db->row("SELECT `lastlogintimes`,`webtoken` FROM `rp_users` WHERE `username`='{$username}'");
		$lastlogintimes = intval($user['lastlogintimes']) + 86400;
		$nowtime = time();
		$result['state'] = 200;
		if($lastlogintimes < $nowtime){
			//登录失效，要重新登录了
			$result['state'] = 100;
			$result['msgid'] = 10001;
			//return Gateway::sendToCurrentClient(json_encode($result));
		}
		if($token != $user['webtoken']){
			//登录的token失效，要重新登录了
			$result['state'] = 100;
			$result['msgid'] = 10002;
			//return Gateway::sendToCurrentClient(json_encode($result));
		}
		return $result;
   }
  
}
